#include <stdio.h>
#include <string>

#include "binary_patterns.h"
#include "grate/dfa.h"
#include "grate/calculator.h"
#include "grate/eigenvalue.h"
#include "grate/util/common.h"

using namespace growth_rate;  // NOLINT
using namespace binary_patterns;  // NOLINT

static const size_t kBufferSize = 1024;

static bool parse_next_input(
    FILE *input_file, std::string *pattern, size_t *root_length,
    size_t *queue_capacity, size_t *trie_capacity) {
  char buffer[kBufferSize];
  if (!fgets(buffer, kBufferSize, input_file))
    return false;
  char pattern_buffer[kBufferSize];
  *queue_capacity = 0;
  *trie_capacity = 0;
  if (sscanf(buffer, "%s %ld %ld %ld", pattern_buffer, root_length,  // NOLINT
             queue_capacity, trie_capacity) < 2) {
    fprintf(stderr, "Input string format: pattern root_length "
                    "[queue_size] [trie_capacity]\n");
    return false;
  }
  *pattern = pattern_buffer;
  return true;
}

static void open_report_file(const std::string &pattern, size_t root_length) {
  char filename[kBufferSize];
  snprintf(filename, kBufferSize, "%s_r%ld.txt", pattern.c_str(), root_length);
  SetReportFile(filename);
}

static double solve_input(const std::string &pattern, size_t root_length,
                          size_t queue_capacity, size_t trie_capacity) {
  open_report_file(pattern, root_length);
  LexminAntiDictionary *AD = get_antidictionary_for_pattern(
    pattern, root_length, queue_capacity, trie_capacity);
  EigenvalueOptions options;
  options.precision = 1e-10;
  options.verbosity = true;
  return Calculator::get_language_growth_rate(AD, true, options);
}

int main(int argc, char *argv[]) {
  if (argc > 3) {
    fprintf(stderr, "Usage: %s [input_file] [output_file]\n", argv[0]);
    return 1;
  }
  FILE *input_file = stdin;
  FILE *output_file = stdout;
  if (argc > 1)
    input_file = fopen(argv[1], "r");
  if (argc > 2)
    output_file = fopen(argv[2], "w");
  std::string pattern;
  size_t root_length, queue_capacity, trie_capacity;
  while (parse_next_input(input_file, &pattern, &root_length,
                          &queue_capacity, &trie_capacity)) {
    double grate = solve_input(pattern, root_length, queue_capacity,
                               trie_capacity);
    fprintf(output_file, "growth rate: %.12lf\n", grate);
    fflush(output_file);
  }
  fclose(input_file);
  fclose(output_file);
  return 0;
}
